package br.com.advance.automacao.web.administrativo;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jfree.util.Log;
import org.primefaces.context.RequestContext;
import org.primefaces.event.FileUploadEvent;
import org.springframework.beans.factory.annotation.Autowired;

import br.com.advance.automacao.model.CLP;
import br.com.advance.automacao.model.Erro;
import br.com.advance.automacao.services.CLPService;
import br.com.advance.automacao.services.ErroService;
import br.com.advance.automacao.services.exceptions.ValidationException;
import br.com.advance.automacao.web.utils.BaseBean;

@ManagedBean
@ViewScoped
public class ImportarXLSErrosMBean extends BaseBean {

	/**
	 *
	 */
	private static final long serialVersionUID = 4180491670576658298L;

	private static final Logger logger = Logger.getLogger(ImportarXLSErrosMBean.class);

	@Autowired
	private ErroService erroService;

	@Autowired
	private CLPService clpService;

	private String idCLP;
	private CLP clp;
	private InputStream arquivo;
	private String nomeArquivo;
	private String contentType;

	private static final String XLSX = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";

	public void initialize() {
		logger.info("initialize...");
	}

	protected boolean verificaUsuarioLogado() {
		return true;
	}

	public void initializeAfter() {
		logger.info("initializeAfter...");
		clp = clpService.buscarPorId(Long.parseLong(idCLP));
	}

    public void upload(FileUploadEvent event) {
        try {
        	arquivo = event.getFile().getInputstream();
        	nomeArquivo = event.getFile().getFileName();
        	contentType = event.getFile().getContentType();
        } catch (IOException e) {
        	logger.warn("Erro ao converter arquivo recebido.", e);
        }
    }

	public void processar() {
		List<String> errosAoProcessar = new ArrayList<String>();
		try {
			if(arquivo == null) {
				throw new ValidationException("Nenhum arquivo selecionado");
			} else {
				Workbook workbook = null;
				Sheet sheet = null;
				if(XLSX.equals(contentType)) {
		            workbook = new XSSFWorkbook(arquivo);
		            sheet = workbook.getSheetAt(0);
				} else {
					workbook = new HSSFWorkbook(arquivo);
		            sheet = workbook.getSheetAt(0);
				}
				criarErro(sheet, errosAoProcessar);
				workbook.close();
			}
		} catch (ValidationException e) {
			FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_WARN, e.getMessage(), null);
			FacesContext.getCurrentInstance().addMessage(null, message);
			return;
		} catch (IOException e) {
			Log.error("Erro ao processar arquivo excel", e);
			FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_WARN, e.getMessage(), null);
			FacesContext.getCurrentInstance().addMessage(null, message);
			return;
		}
		RequestContext.getCurrentInstance().closeDialog(errosAoProcessar);
	}

	private void criarErro(Sheet sheet, List<String> errosAoProcessar) {
		Iterator<Row> rowIterator = sheet.iterator();
		for (int i = 0; rowIterator.hasNext(); i++) {
		    Row row = rowIterator.next();
		    if(row.getCell(0) == null || row.getCell(1) == null) {
		    	return;
		    }
		    String codigo = getValue(row.getCell(0));
		    String descricao = getValue(row.getCell(1));
		    if (StringUtils.isBlank(codigo) || StringUtils.isBlank(descricao)) {
		    	Log.warn("Provavel erro foi encontrado na linha número: " + i);
		    	errosAoProcessar.add("Erro ao processar linha número: " + i + " Motivo: Código ou Descrição Inválidos.");
		    } else {
		    	Erro erro = new Erro();
				erro.setClp(new CLP());
				erro.setClp(clp);
				erro.setCodigo(codigo);
				erro.setDescricao(descricao);
				erro.setAtivo(Boolean.TRUE);
				try {
					erroService.criar(erro);
				} catch (Exception e) {
					Log.warn("Erro codigo: " + erro.getCodigo() + " | Descricao: " + erro.getDescricao() + " - " + e.getMessage());
					errosAoProcessar.add("Erro ao processar linha número: " + i + " Motivo: " + e.getMessage());
				}
		    }
		}
	}

	private String getValue(Cell cell) {
		switch (cell.getCellType()) {
        case Cell.CELL_TYPE_STRING:
            return cell.getStringCellValue();
        case Cell.CELL_TYPE_NUMERIC:
            return String.valueOf((int) cell.getNumericCellValue());
        case Cell.CELL_TYPE_BOOLEAN:
            return String.valueOf(cell.getBooleanCellValue());
        default :
        	return null;
        }
	}

	public void cancelaImportacaoXLS() {
		RequestContext.getCurrentInstance().closeDialog(null);
	}

	public String getIdCLP() {
		return idCLP;
	}

	public void setIdCLP(String idCLP) {
		this.idCLP = idCLP;
	}

	public CLP getClp() {
		return clp;
	}

	public void setClp(CLP clp) {
		this.clp = clp;
	}

	public String getNomeArquivo() {
		return nomeArquivo;
	}

	public void setNomeArquivo(String nomeArquivo) {
		this.nomeArquivo = nomeArquivo;
	}

}
